using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using AutumnEngine.Modules;
using System.IO;

namespace AutumnEngine
{
    public partial class Scene
    {
        /// <summary>
        /// Loads the scene from the specified path.
        /// </summary>
        /// <param name="path">The path.</param>
        public void Load(string path)
        {
            //Clear scene
            this.Nodes.Clear();
            if (Engine.Modules.Contains("Engine.PhysicsManager"))
                Engine.Modules.PhysicsManager.RemoveSimNodes(this.ID);
            /*
             * create binary reader
             * foreach stage (type of node)
             * read number
             * if number = 0, skip, otherwise
             * read all names
             * read all textures
             * read all X pos
             * read all Y pos
             * read all R
             * B
             * G
             * A
             * read all rotation
             * read all scale
             * repeat for all stages
             * read names of all used stages
             * read their paths
            */

            //Open
            string fix = StorageContainer.TitleLocation + "/" + path;
            FileStream fs = File.OpenRead(fix);
            BinaryReader reader = new BinaryReader(fs);
            Dictionary<string, Node> nodes = new Dictionary<string, Node>();
            Dictionary<string, Marker> markers = new Dictionary<string, Marker>();
            Dictionary<string, SpriteNode> spriteNodes = new Dictionary<string, SpriteNode>();
            Dictionary<string, PhysicsSpriteNode> physicsSpriteNodes = new Dictionary<string, PhysicsSpriteNode>();
            Dictionary<string, LabelNode> labels = new Dictionary<string, LabelNode>();
            ///////////////////
            //Read 'Nodes'
            int count = reader.ReadInt32();
            if (count != 0)
            {
                
                for (int i = 0; i < count; i++)
                {
                    string name = reader.ReadString();
                    Node tmp = new Node();
                    Vector2 pos = new Vector2((float)reader.ReadInt32(), (float)reader.ReadInt32());
                    tmp.Position = pos;
                    nodes.Add(name, tmp);
                }
            }

            //Read markers
            count = reader.ReadInt32();
            if (count != 0)
            {

                for (int i = 0; i < count; i++)
                {
                    string name = reader.ReadString();
                    Marker tmp = new Marker();
                    Vector2 pos = new Vector2((float)reader.ReadInt32(), (float)reader.ReadInt32());
                    tmp.Position = pos;
                    markers.Add(name, tmp);
                }
            }

            //SpriteNodes
            //Formwat
            /*
             * Pos X
             * Pos Y
             * StrTexture
             * Scale X
             * Scale Y
             * Rotation
             * Origin X
             * Origin Y
             * Color R
             * Color G
             * Color B
             * Color A
            */
            count = reader.ReadInt32();
            if (count != 0)
            {
                for (int i = 0; i < count; i++)
                {
                    string name = reader.ReadString();
                    int x = reader.ReadInt32();
                    int y = reader.ReadInt32();
                    SpriteNode tmp = new SpriteNode(reader.ReadString());
                    tmp.Position = new Vector2(x, y);
                    Vector2 scale = new Vector2(reader.ReadInt32(), reader.ReadInt32());
                    tmp.Scale = scale;
                    float rot = (float)reader.ReadDouble();
                    tmp.Rotation = rot;
                    Vector2 or = new Vector2(reader.ReadInt32(), reader.ReadInt32());
                    tmp.Origin = or;
                    Color c = new Color(reader.ReadByte(), reader.ReadByte(), reader.ReadByte(), reader.ReadByte());
                    tmp.Color = c;
                    spriteNodes.Add(name, tmp);
                }
            }

            //Physics sprite nodes
            //Formwat
            /*
             * Pos X
             * Pos Y
             * StrTexture
             * Scale X
             * Scale Y
             * Rotation
             * Origin X
             * Origin Y
             * Color R
             * Color G
             * Color B
             * Color A
             * byte BodyType
             * int width
             * int height
             * double mass
             * bool static
            */

            count = reader.ReadInt32();
            if (count != 0)
            {
                for (int i = 0; i < count; i++)
                {
                    string name = reader.ReadString();
                    int x = reader.ReadInt32();
                    int y = reader.ReadInt32();
                    string text = reader.ReadString();
                    Vector2 scale = new Vector2(reader.ReadInt32(), reader.ReadInt32());
                    float rot = (float)reader.ReadDouble();
                    Vector2 or = new Vector2(reader.ReadInt32(), reader.ReadInt32());
                    Color c = new Color(reader.ReadByte(), reader.ReadByte(), reader.ReadByte(), reader.ReadByte());
                    BodyType type = (BodyType)reader.ReadByte();
                    int width = reader.ReadInt32();
                    int height = reader.ReadInt32();
                    if (height <= 0)
                        height = 1;
                    float mass =  (float)reader.ReadDouble();
                    if (mass <= 0f)
                        throw new Exception("0 mass on " + name);
                    PhysicsSpriteNode tmp = new PhysicsSpriteNode(text, type, width, height,mass);
                    
                    tmp.Position = new Vector2(x, y);
                    tmp.Scale = scale;
                    tmp.Rotation = rot;
                    tmp.Origin = or;
                    tmp.Color = c;
                    tmp.Static = reader.ReadBoolean();
                    physicsSpriteNodes.Add(name, tmp);
                }
            }

            //Labels
            //Formwat
            /*
             * Pos X
             * Pos Y
             * StrText
             * StrFont
             * dobule scale
             * Rotation
             * Origin X
             * Origin Y
             * Color R
             * Color G
             * Color B
             * Color A
            */
            count = reader.ReadInt32();
            if (count != 0)
            {
                for (int i = 0; i < count; i++)
                {
                    string name = reader.ReadString();
                    int x = reader.ReadInt32();
                    int y = reader.ReadInt32();
                    string txt = reader.ReadString();
                    LabelNode tmp = new LabelNode(reader.ReadString());
                    tmp.Text = txt;
                    tmp.Position = new Vector2(x, y);
                    float scale = (float)reader.ReadDouble();
                    tmp.Scale = scale;
                    float rot = (float)reader.ReadDouble();
                    tmp.Rotation = rot;
                    Vector2 or = new Vector2(reader.ReadInt32(), reader.ReadInt32());
                    tmp.Origin = or;
                    Color c = new Color(reader.ReadByte(), reader.ReadByte(), reader.ReadByte(), reader.ReadByte());
                    tmp.Color = c;
                    labels.Add(name, tmp);
                }
            }


            //Texture name/path combos
            List<string> paths, names;
            names = new List<string>();
            int co = reader.ReadInt32();
            for (int i = 0; i < co; i++)
            {
                names.Add(reader.ReadString());
            }
            paths = new List<string>();
            for (int i = 0; i < co; i++)
            {
                paths.Add(reader.ReadString());
            }

            for (int i = 0; i < co; i++)
            {
                //Load the textures
                Engine.Modules.TextureManager.AddTexture(names[i], paths[i]);
            }
            paths.Clear();
            names.Clear();
            //Font name/path combos
            int p = reader.ReadInt32();
            for (int i = 0; i < p; i++)
            {
                names.Add(reader.ReadString());
            }
            paths = new List<string>();
            for (int i = 0; i < p; i++)
            {
                paths.Add(reader.ReadString());
            }

            for (int i = 0; i < p; i++)
            {
                //Load the textures
                Engine.Modules.TextureManager.AddTexture(names[i], paths[i]);
                Engine.Modules.FontManager.AddFont(names[i], paths[i]);
            }

            

            //Add the nodes to the scene
            foreach (KeyValuePair<string, Node> n in nodes)
            {
                AddNode(n.Key, n.Value);
            }
            foreach (KeyValuePair<string, Marker> n in markers)
            {
                AddNode(n.Key, n.Value);
            }

            foreach (KeyValuePair<string, SpriteNode> n in spriteNodes)
            {
                AddNode(n.Key, n.Value);
            }

            foreach (KeyValuePair<string, PhysicsSpriteNode> n in physicsSpriteNodes)
            {
                AddNode(n.Key, n.Value);
                
            }

            foreach (KeyValuePair<string, LabelNode> n in labels)
            {
                AddNode(n.Key, n.Value);
            }

            ///////////////////
            //Close
            reader.Close();            
            fs.Close();
            
        }
    }
}